package com.ywwxhz.plugins.tasks;

import android.app.ActivityManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ThumbnailUtils;
import android.os.Handler;
import android.widget.RemoteViews;

import com.ywwxhz.Interface.IModleService;
import com.ywwxhz.Util.PreferencesKit;
import com.ywwxhz.Util.ToolKit;
import com.ywwxhz.plugins.tasks.receiver.CleanReceiver;
import com.ywwxhz.plugins.tasks.widget.ProcessWidget;
import com.ywwxhz.taskmgr.R;

import java.util.List;

public class TaskModel implements IModleService {
    public static final int WIDGET_DISABLE = 0;
    public static final int WIDGET_ENABLE = 1;
    public static final int KILL_ALL_PROC = 2;
    public static final int AUTO_KILL_ENABLE = 3;
    public static final int AUTO_KILL_DISABLE = 4;
    public static final int LOCK_SCREEN_ENABLE = 5;
    public static final int LOCK_SCREEN_DISABLE = 6;
    public static final int MODEL = 3;
    public static final String PARAM = "TASK_PARAM";
    private static TaskModel instance;
    private ActivityManager am = null;
    private int size = 24; // dp
    private int width = 180, height = 54;
    private float hfix, vfix;
    private PackageManager pm = null;
    private Context context;
    private int auto_kill_rate;
    private String ignorelist;
    private int widget_update_rate;
    private CleanReceiver myReceiver;
    private Runnable auto_kill_thread = new Runnable() {
        public void run() {
            handler.removeCallbacks(auto_kill_thread);
            killRunningApp(null, false);
            auto_kill_rate = PreferencesKit.getInt(context, "autokillFlushRate", 600000);
            handler.postDelayed(this, auto_kill_rate);
        }
    };
    private Handler handler = new Handler();
    private Runnable Widget_update_thread = new Runnable() {
        public void run() {
            handler.removeCallbacks(Widget_update_thread);
            updateProcView();
            handler.postDelayed(this, widget_update_rate);
        }
    };
    private boolean updateWidget = false;
    private boolean autoKill = false;
    private boolean screenoffkill = false;
    private String TAG = "TaskModel";

    private TaskModel(Context context) {
        this.context = context;
        myReceiver = new CleanReceiver();
        am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        pm = context.getPackageManager();
        sizeUpdate(context);
        onRecover(context);
    }

    public static TaskModel getInstance(Context context) {
        if (instance == null) {
            instance = new TaskModel(context);
        }
        return instance;
    }

    private void sizeUpdate(Context context) {
        size = ToolKit.dip2px(context, size);
        width = ToolKit.dip2px(context, width);
        height = ToolKit.dip2px(context, height);
        hfix = (float) width % size / (width / size + 1);
        vfix = (float) height % size / (height / size + 1);
    }

    @Override
    public void execute(Intent intent) {
        ToolKit.Log(TAG, "" + intent.getExtras().toString());
        switch (intent.getIntExtra(PARAM, -1)) {
            case AUTO_KILL_DISABLE:
                ToolKit.Log(TAG, "AUTO_KILL_DISABLE");
                handler.removeCallbacks(auto_kill_thread);
                autoKill = false;
                break;
            case AUTO_KILL_ENABLE:
                ToolKit.Log(TAG, "AUTO_KILL_ENABLE");
                handler.post(auto_kill_thread);
                autoKill = true;
                break;
            case KILL_ALL_PROC:
                ToolKit.Log(TAG, "KILL_ALL_PROC");
                killRunningApp(intent.getStringExtra("from"), true);
                break;
            case WIDGET_DISABLE:
                ToolKit.Log(TAG, "WIDGET_DISABLE");
                handler.removeCallbacks(Widget_update_thread);
                updateWidget = false;
                break;
            case WIDGET_ENABLE:
                ToolKit.Log(TAG, "WIDGET_ENABLE");
                handler.post(Widget_update_thread);
                updateWidget = true;
                break;
            case LOCK_SCREEN_ENABLE:
                ToolKit.Log(TAG, "LOCK_SCREEN_ENABLE");
                lockScreenReceiver(true);
                break;
            case LOCK_SCREEN_DISABLE:
                ToolKit.Log(TAG, "LOCK_SCREEN_DISABLE");
                lockScreenReceiver(false);
                break;
        }
    }

    @Override
    public void onConfigChange(Configuration newConfig) {
        if (getStatus()) {
            if (ToolKit.isTablet(context)) {
                if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    size = 20;
                    width = 165;
                    height = 40;
                    sizeUpdate(context);
                } else {
                    size = 24;
                    width = 180;
                    height = 54;
                    sizeUpdate(context);
                }
                handler.post(Widget_update_thread);
            }
        }
    }

    @Override
    public void onDestroy() {
        handler.removeCallbacks(auto_kill_thread);
        handler.removeCallbacks(Widget_update_thread);
        lockScreenReceiver(false);
    }

    @Override
    public boolean getStatus() {
        ToolKit.Log(TAG, "autoKill: " + autoKill + " screenoffkill: " + screenoffkill + " updateWidget: " + updateWidget);
        return autoKill || screenoffkill || updateWidget;
    }

    @Override
    public void onRecover(Context context) {
        autoKill = false;
        updateWidget = false;
        handler.removeCallbacks(auto_kill_thread);
        handler.removeCallbacks(Widget_update_thread);
        if (PreferencesKit.getboolean(context, context.getString(R.string.pref_autokill_key), false)) {
            handler.post(auto_kill_thread);
            autoKill = true;
        }
        ComponentName localComponentName = new ComponentName(context,
                ProcessWidget.class);
        if (AppWidgetManager.getInstance(context).getAppWidgetIds(
                localComponentName).length > 0) {
            handler.post(Widget_update_thread);
            updateWidget = true;
        }
        lockScreenReceiver(PreferencesKit.getboolean(context, context.getString(R.string.pref_lockscreen_key), false));
    }

    /**
     * 注册锁屏广播
     */
    private void lockScreenReceiver(boolean enable) {
        // 动态注册BroadcastReceiver
        screenoffkill = enable;
        try {
            if (enable) {
                IntentFilter filter = new IntentFilter();
                filter.addAction("android.intent.action.SCREEN_OFF");
                filter.addAction("android.intent.action.USER_PRESENT");
                context.registerReceiver(myReceiver, filter);
            } else {
                context.unregisterReceiver(myReceiver);
            }
        } catch (Exception ignored) {
        }
    }

    /**
     * 杀死全部进程不包括免杀列表
     */
    private synchronized void killRunningApp(String from, boolean show) {
        ignorelist = ToolKit.getIgnoreList(context);
        // 通过调用ActivityManager的getRunningAppProcesses()方法获得系统里所有正在运行的进程
        List<ActivityManager.RunningAppProcessInfo> appProcessList = am
                .getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcessList) {
            String[] pkgNameList = appProcess.pkgList; // 获得运行在该进程里的所有应用程序包

            ApplicationInfo appInfo;
            // 输出所有应用程序的包名
            for (String aPkgNameList : pkgNameList) {
                try {
                    appInfo = context.getPackageManager().getApplicationInfo(
                            aPkgNameList,
                            PackageManager.GET_UNINSTALLED_PACKAGES);
                    if (ignorelist.contains(appInfo.packageName)
                            || ignorelist.contains(appProcess.processName)) {
                        break;
                    }
                    ToolKit.Kill_Proc(aPkgNameList, am);
                } catch (NameNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
        if (show) {
            ToolKit.MakeToast(context,
                    "任务清理完成，可用内存 " + ToolKit.getAvaliableMemory(context, am));
        }
        if (from != null) {
            updateProcView();
        }
    }

    /**
     * 更新进程桌面小控件
     */
    public synchronized void updateProcView() {
        ignorelist = ToolKit.getIgnoreList(context);
        widget_update_rate = PreferencesKit.getInt(context, "widgetFlushRate", 3000);
        RemoteViews mRemoteViews = new RemoteViews(context.getPackageName(),
                R.layout.widget_proc);

        mRemoteViews.setImageViewBitmap(R.id.proc_list, getRuningBitmap());
        Intent intent = new Intent(context, CleanReceiver.class);
        intent.putExtra("from", "");
        // 拿到一个PendingIntent对象，来发送一条广播
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
                intent, PendingIntent.FLAG_UPDATE_CURRENT);
        mRemoteViews.setOnClickPendingIntent(R.id.proc_list, pendingIntent);
        mRemoteViews.setTextViewText(R.id.avalible,
                ToolKit.getAvaliableMemory(context, am));
        ComponentName localComponentName = new ComponentName(context,
                ProcessWidget.class);
        AppWidgetManager.getInstance(context).updateAppWidget(
                localComponentName, mRemoteViews);
    }

    /**
     * 获取运行任务的图片
     */
    private Bitmap getRuningBitmap() {
        float left = hfix;
        float top = vfix;
        Bitmap bitmaphoder = Bitmap.createBitmap(width, height,
                Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmaphoder);
        canvas.drawColor(Color.argb(80, 255, 255, 255));
        // 通过调用ActivityManager的getRunningAppProcesses()方法获得系统里所有正在运行的进程
        List<ActivityManager.RunningAppProcessInfo> appProcessList = am
                .getRunningAppProcesses();
        boolean over = false;
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcessList) {
            String[] pkgNameList = appProcess.pkgList; // 获得运行在该进程里的所有应用程序包
            // 输出所有应用程序的包名
            if (over)
                break;

            ApplicationInfo appInfo;
            for (String aPkgNameList : pkgNameList) {
                // 根据包名查询特定的ApplicationInfo对象
                try {
                    appInfo = pm.getApplicationInfo(aPkgNameList,
                            PackageManager.GET_UNINSTALLED_PACKAGES);
                    if (ignorelist.contains(appInfo.packageName)
                            || ignorelist.contains(appProcess.processName)) {
                        break;
                    }
                    if (top < height) {
                        if (left + size > width) {
                            left = hfix;
                            top += size + vfix;
                        }
                        if (top + size > height) {
                            over = true;
                            break;
                        }
                        Drawable d = appInfo.loadIcon(pm);
                        Bitmap bmp = ((BitmapDrawable) d).getBitmap();
                        bmp = ThumbnailUtils.extractThumbnail(bmp, size, size);
                        canvas.drawBitmap(bmp, left, top, null);// 画图
                        left += size + hfix;
                    } else {
                        over = true;
                        break;
                    }
                } catch (NameNotFoundException e) {
                    e.printStackTrace();
                } // 0代表没有任何标记;
            }
        }
        appProcessList.clear();
        return bitmaphoder;
    }


}
